/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sk.uniba.fmph.asdf.gui.views;

import com.alee.extended.statusbar.WebStatusBar;
import com.alee.laf.label.WebLabel;
import com.alee.laf.menu.WebMenu;
import com.alee.laf.menu.WebMenuBar;
import com.alee.laf.menu.WebMenuItem;
import com.alee.laf.tabbedpane.TabStretchType;
import com.alee.laf.tabbedpane.TabbedPaneStyle;
import com.alee.laf.tabbedpane.WebTabbedPane;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import sk.uniba.fmph.asdf.Session;
import sk.uniba.fmph.asdf.exceptions.DatabaseException;
import sk.uniba.fmph.asdf.exceptions.OfflineException;
import sk.uniba.fmph.asdf.gui.GuiUtils;
import sk.uniba.fmph.asdf.gui.dialogs.Dialog;
import sk.uniba.fmph.asdf.gui.frames.AccountEditorFrame;
import sk.uniba.fmph.asdf.gui.frames.EvaluationFrame;
import sk.uniba.fmph.asdf.gui.frames.ExportFrame;
import sk.uniba.fmph.asdf.gui.frames.Frame;
import sk.uniba.fmph.asdf.gui.frames.TemplateEditorFrame;
import sk.uniba.fmph.asdf.gui.frames.TestCreatorFrame;

/**
 *
 * @author mt
 */
public class MainView extends View {

	public static final int NO_ICON = 70;
	public static final int OK_ICON = 71;
	public static final int SYNC_ICON = 72;
	public static final int WAIT_ICON = 73;
	private final String applicationName = "Správa testov";
	private String applicationSubtitle = "";
	private String applicationAccount = "";
	private WebTabbedPane tabs;
	private WebStatusBar statusBar;
	private WebLabel statusLabel;

	public MainView() {
		super(JFrame.EXIT_ON_CLOSE);
		invokeSynchronization();
		initComponents();
	}

	@Override
	public void display() {
		super.display();
		setExtendedState(this.getExtendedState() | MAXIMIZED_BOTH);
	}

    /**
     * Inicializacia komponentov
     */
	@Override
	protected final void initComponents() {
		setPreferredSize(new Dimension(1024, 768));
		setMinimumSize(new Dimension(1024, 768));
		getContentPane().setLayout(new BorderLayout());

		WebMenuBar menuBar = new WebMenuBar();
		menuBar.setUndecorated(true);
		WebMenu menu = new WebMenu("Menu");
		final WebMenuItem exitItem = new WebMenuItem("Exit", GuiUtils.getIcon("exit"));
		exitItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		menu.add(exitItem);
		menuBar.add(menu);
		setJMenuBar(menuBar);


		tabs = new WebTabbedPane();
		tabs.setTabbedPaneStyle(TabbedPaneStyle.attached);
		tabs.setTabStretchType(TabStretchType.never);
		tabs.addTab("Hodnotenie testov", GuiUtils.getIcon("evaluation"), new EvaluationFrame(this));
		tabs.addTab("Tvorba šablón", GuiUtils.getIcon("template"), new TemplateEditorFrame(this));
		tabs.addTab("Tvorba sady testov", GuiUtils.getIcon("test"), new TestCreatorFrame(this));
		tabs.addTab("Export", GuiUtils.getIcon("export"), new ExportFrame(this));
		tabs.addTab("Administrácia účtov", GuiUtils.getIcon("user_panel"), new AccountEditorFrame(this));

        if (!Session.isOnline()) {
            tabs.setEnabledAt(1, false);
//            tabs.setEnabledAt(2, false);
            tabs.setEnabledAt(4, false);
        }

		tabs.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				Frame tab = (Frame) tabs.getSelectedComponent();
				/**/
				if (tab instanceof EvaluationFrame) {
					((EvaluationFrame) tab).generateTestTree();
				}
				/**/
				tab.onShow();
			}
		});
		add(tabs, BorderLayout.CENTER);

		statusBar = new WebStatusBar();
		statusLabel = new WebLabel();
		statusLabel.addMouseListener(new MouseListener() {
			@Override
			public void mouseClicked(MouseEvent e) {
				showDialog("StatusMessagesDialog");
			}

			@Override
			public void mousePressed(MouseEvent e) {
				//throw new UnsupportedOperationException("Not supported yet.");
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				//throw new UnsupportedOperationException("Not supported yet.");
			}

			@Override
			public void mouseEntered(MouseEvent e) {
//                throw new UnsupportedOperationException("Not supported yet.");
			}

			@Override
			public void mouseExited(MouseEvent e) {
//                throw new UnsupportedOperationException("Not supported yet.");
			}
		});
		statusBar.add(statusLabel);
		add(statusBar, BorderLayout.PAGE_END);

		clearStatusLabel();
	}

	/* FROM MAINWINDOW */
	/**
	 * Vytvorenie a zobrazenie pozadovaneho dialogu.
	 *
	 * @param name - nazov dialogu
	 */
	public void showDialog(String name) {
		try {
			Class c = Class.forName("sk.uniba.fmph.asdf.gui.dialogs." + name);
			Constructor ctor = c.getDeclaredConstructor(MainView.class);
			Dialog dialog = (Dialog) ctor.newInstance(this);

			// nastavenie pozicie dialogu do stredu hlavneho okna
			dialog.setLocationRelativeTo(this);
			dialog.setLocation((this.getWidth() - dialog.getWidth()) / 2,
							(this.getHeight() - dialog.getHeight()) / 2);

			dialog.setVisible(true);
		} catch (IllegalArgumentException | SecurityException | InvocationTargetException |
						NoSuchMethodException | InstantiationException | IllegalAccessException |
						ClassNotFoundException ex) {
			//Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	/**
	 * Vykonanie akcii po logine. Nastavenie titulku okna, synchronizacia a
	 * zobrazenie predvoleneho viewu.
	 */
	public final void invokeSynchronization() {
		setAccount(Session.getAccount().getEmail());
		synchronizeLocalFiles();
		if (Session.isOnline()) {
			synchronizeWithDB();
		}
	}

	/**
	 * Vykona vzdialenu synchronizaciu a vrati ci prebehla uspesne. V pripade
	 * zachytenia exceptionu vypise chybu v dialogovom okne. Tiez zaznamena spravu
	 * o synchronizacii medzi stavove spravy.
	 *
	 * @return boolean
	 */
	public boolean synchronizeWithDB() {
		JTextArea textArea = new JTextArea();
		textArea.setColumns(30);
		textArea.setOpaque(false);
		textArea.setEditable(false);
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);

		boolean result = false;
        Session.addStatusMessage("Synchronizujem so serverom...");
		if (statusBar != null) {
			setStatusLabel("Synchronizujem so serverom...", MainView.SYNC_ICON);
		}
		try {
			Session.synchronize();
			result = true;
		} catch (OfflineException ex) {
			textArea.setText("Nepodarilo sa pripojiť na server:\n" + ex.getMessage());
			JOptionPane.showMessageDialog(this, textArea, "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (DatabaseException ex) {
			textArea.setText("Synchronizácia dát s databázou zlyhala:\n" + ex.getMessage());
			JOptionPane.showMessageDialog(this, textArea, "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (JSchException | SftpException ex) {
			textArea.setText("Synchronizácia súborov so serverom zlyhala:\n" + ex.getMessage());
			JOptionPane.showMessageDialog(this, textArea, "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (IOException ex) {
			textArea.setText("Nepodarilo sa uložiť synchronizované súbory:\n" + ex.getMessage());
			JOptionPane.showMessageDialog(this, textArea, "Chyba!", JOptionPane.ERROR_MESSAGE);
		}
		if (statusBar != null) {
			clearStatusLabel();
		}

		return result;
	}

	/**
	 * Vykona lokalnu synchronizaciu a vrati ci prebehla uspesne. V pripade
	 * zachytenia exceptionu vypise chybu v dialogovom okne. Tiez zaznamena spravu
	 * o synchronizacii medzi stavove spravy.
	 *
	 * @return boolean
	 */
	public boolean synchronizeLocalFiles() {
		JTextArea textArea = new JTextArea();
		textArea.setColumns(30);
		textArea.setOpaque(false);
		textArea.setEditable(false);
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);

		boolean result = false;
        Session.addStatusMessage("Synchronizujem lokálne súbory...");
		if (statusLabel != null) {
			setStatusLabel("Synchronizujem lokálne súbory...", MainView.SYNC_ICON);
		}
		try {
			Session.synchronizeMemoryAndFiles();
			result = true;
		} catch (IOException ex) {
			textArea.setText("Nepodarilo sa synchronizovať lokálne súbory:\n" + ex.getMessage());
			JOptionPane.showMessageDialog(this, textArea, "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (ClassNotFoundException ex) {
			textArea.setText("Chyba pri spracovaní lokálnych súborov:\n" + ex.getMessage());
			JOptionPane.showMessageDialog(this, textArea, "Chyba!", JOptionPane.ERROR_MESSAGE);
		}
		if (statusBar != null) {
			clearStatusLabel();
		}

		return result;
	}

	/**
	 * Nastavi treti segment titulku okna - aktualne prihlaseneho pouzivatela
	 *
	 * @param account
	 */
	public void setAccount(String account) {
		applicationAccount = account;

		updateTitle();
	}

	/**
	 * Aktualizuje titulok okna. Spoji nazov aplikacie, podtitulok a meno
	 * prihlaseneho pouzivatela (ak su nastavene) a vysledok nastavi ako titulok.
	 */
	private void updateTitle() {
		String title = applicationName;
		if (!applicationSubtitle.equals("")) {
			title += " - " + applicationSubtitle;
		}
		if (!applicationAccount.equals("")) {
			title += " [" + applicationAccount + "]";
		}
		setTitle(title);
	}

	public boolean setStatusLabel(final String text, final int statusIcon) {

		statusLabel.setText(text);
		switch (statusIcon) {
			case OK_ICON:
				statusLabel.setIcon(GuiUtils.getIcon("yes"));
				break;
			case SYNC_ICON:
				statusLabel.setIcon(GuiUtils.getIcon("sync"));
				break;
			case WAIT_ICON:
				statusLabel.setIcon(GuiUtils.getIcon("wait"));
				break;
		}
		statusBar.revalidate();
		statusLabel.revalidate();
		statusLabel.repaint();
		return true;
	}

    /**
     * Nastavenie popisu statusovej listy
     * @param text popis
     */
	public void setStatusLabel(final String text) {
		setStatusLabel(text, NO_ICON);
	}

    /**
     * Nastavenie popisu na preddefinovany text "Aplikacia sa nachadza v synchronizovanom stave."
     */
	public void clearStatusLabel() {
        Session.addStatusMessage("Aplikácia sa nachádza v synchronizovanom stave.");
		setStatusLabel("Aplikácia sa nachádza v synchronizovanom stave.", OK_ICON);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
	}
}
